home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
011-020
/
amok18
/
popup-menu
/
pop.mod.dok
< prev
next >
Wrap
Text File
|
1993-11-04
|
21KB
|
447 lines
Dokumentation zum Hilfsprogramm 'PopUp-Menüs'.
(*---------------------------------------------------------------------------
:Programm : PopUp-Modul
:Version : 2.01 als Modula-2 Hilfsmodule pop.def und pop.mod.
:Wozu : Darstellung von PopUp-Menüs auf dem Amiga
:Bemerkung: Funktion ähnlich Intuition-Menüs.
:Version : 1.0, pop.c by Derek Zahn,
(Gambit Software, Madison WI) July 1987
:Version : 2.0, 1:1 Übersetzung in Modula-2 und
:Version : 2.01, bereinigte und geringfügig verbesserte Version von
:Autor : Jochen P. Kupfer,
:Adresse : Buchenweg 22, D-4006 Erkrath 2,
:Telefon : 02104-40673.
:Zusatz : SIGMA
:Datum : 4/16-Feb-89
:Copyright: PD
:Sprache : Modula-2
:Compiler : M2Amiga V3.2d
---------------------------------------------------------------------------*)
DOKUMENTATION zum PopUp-Menü MODULE
===================================
0. Einführung:
Intuition unterstützt nur Menüs die an der Oberkante des Screens befestigt
sind. Dies ist aber eine unnötige Einschränkung, denn es gibt andere
Windowsysteme (z.B. beim MacIntosh), die 'PopUp-Menüs' unterstüzen. Diese
Menüs können dann irgendwo auf dem Screen erscheinen. Die Hilfsmodule
'pop.def' und 'pop.mod' bieten dem Amiga-Anwender eine zusätzliche Schnitt-
stelle an, mit der er noch experimentieren kann, und die auch noch
erweiterungsfähig ist. Derek Zahn hat diesen Code (pop.c) im Public Domain
Bereich plaziert, zur weiteren Verwendung, Veränderung und Diskussion. Er
hofft, daß ihn jemand brauchbar findet.
1. Besonderheiten:
Das Hilfsmodul bietet die Möglichkeit zum Einsatz von PopUp-Menüs unter
Verwendung von Datenstrukturen, ähnlich denen die bei konventionellen
Intuition Menüs verwendet werden. Wie in Abschnitt 3. und 4 deutlicher
wird, wurden einige Flags zu Kontrolle des PopUp-Menüs hinzugefügt, andere
die hier keinen rechten Sinn ergeben, wurden weggelassen. Einige Variablen
der Intuition-Menü-Struktur werden anders verwendet, als dort angegeben.
Ein möglicher Anwender dieses Hilfsmoduls sollte deshalb die Dokumen-
tation genau durchlesen und die Bedeutung der Flags verstehen. Das Demo-
Programm 'popDemo' zeigt einige einfache Anwendungsbeispiele zum besseren
Verständnis.
Wie aus Abschnitt 2. hervorgeht, besteht die Schnittstelle aus einer sehr
einfachen Funktion, die die Betätigung einer Maustaste abfängt, und
entsprechend der Wahl des Benutzers, einen bestimmten Wert zurück gibt.
Diese Schnittstelle weicht erheblich vom der normalen Intuition
Schnittstelle ab, die eine Nachricht an den MessagePort schickt.
Der Grund für dieses abweichende Verhalten ist die folgende Tatsache:
Das normale Intuition-Menü ist zu jeder Zeit verfügbar, solange das
ensprechende Window aktiv ist (außer wenn das Menü explizit abgeschaltet
wurde). Dieser Mechanismus ist in Intuition auf einem sehr fundamentalen
Niveau programmiert. Es gibt keine klare, allgemein akzeptierte Methode um
dem Anwenderprogramm die Verantwortung for die Behandlung des 'PopUp-Menüs'
abzunehmen.
Derek Zahn wollte ursprünglich einen eigenen Task programmieren, der
ähnlich selbständig funktioniert wie das Intuition-Menü, und den Anwender
über den IDCMP-Port in der Variablen class über des entsprechende popFlag
(popMenuVerify, popMenuHit, etc.) informiert. Das funktionierte jedoch nie
so richtig, deshalb würde Derek eine Diskussion zu diesem Thema begrüßen.
Trotz des Fehlens der prozedurmäßigen Ausrichtung auf Intuition (die vor-
liegenden PopUp-Menüs funktionieren mehr wie Autorequester), gibt es genug
Anwendungsmöglichkeiten für die vorliegende Schnittstelle. PopUp-Menüs
könnten beispielsweise in einer Textverarbeitung sehr praktisch zur
Änderung der aktuellen Fonts benutzt werden. Die Verwendung der PopUp-
Menüs erspart dem Anwender sehr viele unnötige Bewegungen mit der Maus.
Sie erspart programmtechnischen Aufwand für Gadgets und der Anwender muß
am Anfang nicht gleich alle möglichen Tastaturbefehle können.
PopUp-Menüs verwenden den gleichen MenuItem-RECORD wie Intuition (In C
wird auch die Original-Menu-Struktur verwendet, das geht in Modula-2
nicht.). Die meisten Funktionen der Intuition-Menüs werden von den PopUp-
Menüs in nahezu identischer Art und Weise unterstützt (--> Abschnitt 3./4.).
Es gibt jedoch einige wesentliche Abweichungen. Derek findet, daß das
vorliegende Modul noch unvollständig ist. Es gibt weder SubItems noch
mehrere Menüstreifen, noch die Möglichkeit der 'extended selection'.
Zur weiteren Diskussion dieser und anderer Probleme wird auf den Anhang
verwiesen.
2. PopChoose()
Die Anwender-Schnittstelle wird im Definitions-Modul 'pop.def' wie folgt
beschrieben:
TYPE
popFlags = (menuEnabled,popVerify,popRelease,popTidy,popPointRel,popWinRel,
popRemember,popUsed,pf8,popMovePointer,pf10,pf11,
popLeftButton,popRightButton,popTriggerDown,popTriggerUp);
popFlagSet = SET OF popFlags;
(*
* Anmerkung zur Modula-2 Version:
*
* Die Vereinbarung der Flags sieht in C vollkommen anders aus.
* Diese Formulierung hier kommt aber m.E. der M2Amiga-Schreibweise
* am nächsten.
*)
CONST
PopTitleHeight = 10; (* Wenn Sie im Screen-RECORD größere Fonts verwenden,
dann muß dieser Wert in 'ySize+2' geändert werden. *)
TYPE
popMenuPtr = POINTER TO popMenu;
popMenu = RECORD
nextMenu :popMenuPtr; (* Noch nicht implementiert, das könnten Sie tun!*)
leftEdge :INTEGER;
topEdge :INTEGER;
width :INTEGER;
height :INTEGER;
flags :popFlagSet;
menuName :ADDRESS;
firstItem :MenuItemPtr;
END;
(*
* Anmerkung zur Modula-2 Version:
*
* Anders als in C, mußt hier ein eigener popMenu-RECORD definiert werden,
* weil der popFlagSet als Variablentyp in diesem Record benötigt wird.
* Die Variablen jazz... und beat... entfallen.
*)
(*
* PROCEDURE PopChoose(menPtr:popMenuPtr;winPtr:WindowPtr):LONGINT;
*
* menPtr -- Zeiger auf das PopUp-Menü.
* winPtr -- Zeiger auf das Window zu dem das PupUp-Menü gehört.
* winPtr muß #NIL sein, denn es ergibt keinen Sinn, ein PopUp-
* Menü für ein nicht vorhandenes Window zu eröffnen.
*
* Diese Funktion bringt das PopUp-Menü auf den Screen. Sie liefert -1
* zurück, falls entweder ein Fehler beim Aufbau des Menüs passierte,
* oder der Benutzer keine Auswahl getroffen hat.
* Wurde ein MenuItem selektiert, dann gibt die Funktion eine Zahl zwischen
* 0 und n-1 zurück, wobei n die Anzahl der MenuItems ist. Die MenuItems
* werden also von 0 bis n-1 durchnumeriert.
*
* -1 wird auch zurück gegeben, wenn ein Attribut-Item angewählt wurde,
* der bereits mit einem Häkchen versehen, also schon aktiv, ist.
*
* Da mit diesem Hilfsmodul ein eigenes Window eröffnet wird, muß der
* Programmierer selbst darauf achten, daß keine unzulässigen Dinge
* passieren, solange die Funktion aktiv ist.
*)
PROCEDURE PopChoose(menPtr:popMenuPtr;winPtr:WindowPtr):LONGINT;
In dieser Funktion spezifiziert die Variable 'winPtr' das Window, an das
das PopUp-Menü-Window angehängt wird. Das 'popMenu' auf das der Zeiger
'menPtr' zeigt, wird im Abschnitt 3./4. genauer beschrieben.
Falls ein Fehler auftrat, oder keine gültige Auswahl getroffen wurde, gibt
die Funktion -1 zurück. Wurde ein MenuItem selektiert, dann wird eine
nicht negative Zahl zurück gegeben. Dieser Rückgabewert errechnet sich wie
folgt: Der erste MenuItem hat die Nummer 0, der 2. MenuItem die Nummer 1,
etc. Bei n MenuItems hat der letzte Item die Nummer n-1. Dies ist die
gleiche Auswahlmethode wie bei Intuition.
PopChoose() öffnet ein eigenes Window, in das das Menü gezeichnet wird.
Es liegt in der Verantwortung des Programmierers, dafür Sorge zu tragen,
in dieses Fenster nichts geschrieben oder gezeichnet wird.
3. Der popMenu-RECORD
Seine Definition lautet:
popMenu = RECORD
nextMenu :popMenuPtr; (* Noch nicht implementiert, das könnten Sie tun!*)
leftEdge :INTEGER;
topEdge :INTEGER;
width :INTEGER;
height :INTEGER;
flags :popFlagSet;
menuName :ADDRESS;
firstItem :MenuItemPtr;
END;
Die Bedeutung der Variablen:
nextMenu :popMenuPtr; Diese Variable wurde noch nicht verwendet, damit
könnte man mehrere Menüstreifen aneinander hängen - Sie sehen,
es bliebe noch einiges zu tun!
leftEdge,topEdge:INTEGER; Dies sind die Koordinaten der oberen linken
Windowecke. Ihr Wert wird durch die Flags popPointRel,
popWinRel, popTidy und popRemember beeinflußt (--> unten).
width,height:INTEGER; Die Bedeutung deser Variablen weicht stark von
der in Intuition verwendeten ab! Hier stehen Gesamtbreite und
Gesamthöhe des PopUp-Menüs, d.h. das gesamte PopUp-Menü muß
in dieses Rechteck passen!
flags:popFlagSet; Da es in Intuition keine ensprechenden Flags gibt,
mußten hier eigene definiert werden:
menuEnabled: Ist dieses Flag nicht gesetzt, dann liefert
PopChoose() sofort -1 zurück und ist fertig.
popVerify, popRelease und popMovePointer wollte Derek Zahn wohl
noch verwenden, sie kommen aber in 'pop.c' und damit
auch in 'pop.mod' nicht vor!
Als Voreinstellung geben Die Variablen leftEdge und topEdge den absoluten
Offset von der linken oberen Screenecke an. Die folgenden Flags ändern
diese Voreinstellung:
popPointRel: Ist dieses Flag gesetzt, dann geben leftEdge und
topEdge den Offset von der Mauszeigerposition an
wenn PopChoose() aufgerufen wird.
popWinRel: Ist dieses Flag gesetzt, dann geben leftEdge und
topEdge den Offset von der linken oberen Ecke des
aufrufenden Windows an. popPointRel hat Priorität
über popWinRel, falls beide Flags gesetzt sind.
popRemember: Ist dieses Flag gesetzt, und PopChose() wurde schon
einmal aufgerufen, dann werden leftEdge und topEdge so
verändert, daß der zuletzt gewählte MenuItem genau unter
dem Mauszeiger erscheint. Damit ist dieser Item auch gleich
vorgewählt.
popTidy: Ist dieses Flag gesetzt, so garantiert es dafür, daß das
gesamte PopUp-Menü auf den Screen paßt, d.h. der Ort an
dem es erscheint, wird so verändert, daß kein Teil des Menüs
abgeschnitten wird. Die Wirkung der Flags popPointRel,
popWinRel und popRemember wird nötigenfalls soweit
verändert, daß alle MenuItems auf dem Screen sichtbar sind.
popUsed: Dies ist ein internes Flag, es zeigt an ob beim nächsten
Aufruf von PopChoose() das Flag popRemember berücksichtigt
werden soll.
Die nächsten Flags legen die Bedingungen fest, wann ein MenuItem
als selektiert angesehen werden kann. Bitte beachten Sie, daß
es ***absolut notwendig*** ist eines der popFlags popLeftButton
oder popRightButton, sowie ***auch*** eines der popFlags
popTriggerUp oder popTriggerDown zu setzen. Wird diese Bedingung
nicht eingehalten, dann kehrt das Programm vom Aufruf von
PopChoose() nie mehr(!) zurück.
popLeftButton: Behandelt den linken Mausknopf als Auslöser für
die Wahl des MenuItems. Auch popRightButton kann gleich-
zeitig gesetzt sein. Dann wird auch die rechte Maustaste
als Auslöser berücksichtigt.
popRightButton: Behandelt den rechten Mausknopf als Auslöser für
die Wahl des MenuItems.
popTriggerUp: Sorgt dafür, daß ein MenuItem selektiert ist, wenn
der Mausknopf über ihm losgelassen wurde. War der
Mauszeiger nicht über einem Item, dann ist auch keiner
selektiert. Gleichzeitig kann auch das popFlag
popTriggerDown gesetzt sein. In diesem Fall wirken beide.
popTriggerDown: Sorgt dafür, daß ein MenuItem selektiert ist,
wenn der Mausknopf über ihm gedrückt wurde. War der
Mauszeiger nicht über einem Item, dann ist auch keiner
selektiert.
menuName:ADDRESS; Die Bedeutung dieser Variablen ist etwas verwirrend,
da sie auch die Positionierung (in y-Richtung) des PopUp-Menüs
beeinflußt. Ist diese Adresse=NIL, also kein Titel vorhanden,
dann stellt der Offset im MenuItem-RECORD den tatsächlichen Offset
von der linken oberen Ecke des Menüs dar. Ist ein Titel vorhanden,
dann wird er als Menütitel geschrieben. In diesem Fall wird der
Wert von PopTitleHeight (aus pop.def) stillschweigend zu dem
jeweiligen Wert von topEdge im MenuItem-RECORD addiert. Dieses
etwas verwirrende Verhalten resultiert aus der Option, daß der
Menütitel auch weggelassen werden darf und gleichzeitig die
übliche Bedeutung der Intuition-Variablen topEdge beibehalten
wird.
firstItem:MenuItemPtr; Zeiger auf die verkettete Liste der
MenuItem-RECORDs, die das Menü beschreiben. Diese Liste kann
auch leer sein.
4. Der MenuItem-RECORD
Die verwendeten Variablen haben fast die gleiche Besdeutung wie unter
Intuition.
nextItem:MenuItemPtr; Zeigt auf den nächsten MenuItem-RECORD in der
verketteten Liste.
leftEdge,topEdge:INTEGER; Enthalten die Koordinaten der linken oberen Ecke
der Auswahlbox des MenuItems, bezogen auf die linke obere Ecke
des Menüs. Hat das Menü eine Titelleiste, dann wird der Wert von
PopTitleHeight stillschweigend zu topEdge addiert. Dies wird sehr
schnell verständlich, wenn Sie es in der Praxis erproben.
width,height:INTEGER; Bestimmen Höhe und Breite der Auswahlbox.
flags:MenuItemFlagSet; Funktionieren wie unter Intuition; ausgenommen
commSeq und isDrawn. Diese beiden Flags wurden nicht verwendet.
mutualExclude:LONGSET; Funktioniert genau wie unter Intuition.
Alle MenuItems, bei denen das Flag checkIt gesetzt wurde,
können sich gegenseitig auschließen. Wird einer dieser Items
ausgewählt und hat er kein Häkchen, dann bekommt er das
Häkchen und bei allen anderen wird es entfernt. Dieser LONGSET
stellt eine Bitmaske dar, wobei sich jedes Bit auf einen Item
in der verketteten Liste bezieht. Dem ersten MenuItem entspricht
das Bit Nr. 0, dem nächsten Item das Bit Nr. 1, etc. Ist das
ensprechende Bit zu einem MenuItem gesetzt, dann gehört es zur
gleichen mutualExclude-Gruppe wie der aktuelle Item. Wenn Sie
einen Item in seiner eigenen mutualExclude-Gruppe plazieren,
dann kann er niemals selektiert werden. Das wird man normaler-
weise nicht wollen - aber wer weiß?
itemFill,selectFill:ADDRESS; Funktionieren genau wie unter Intuition.
command:CHAR; Diese Variable wird ignoriert.
subItem:MenuItemPtr; Diese Variable wird ignoriert, d.h. SubItems werden
z.Z noch nicht unterstützt.
nextSelect:CARDINAL; Diese Variable wird ignoriert.
Zusatzbemerkung zu Verwendung der MenuItemFlags:
Es gibt keine PopUp-Menü-spezifischen MenuItemFlags. Deshalb hier eine
Beschreibung der Standardflags und ihre Verwendung im PopUp-Menü.
checkIt,checked: Bringen das Häckchen an den MenuItem, genau wie bei
Intuition. PopChoose() gibt -1 zurück, wenn der Anwender einen
Item angewählt hat, der bereits vorher selektiert war.
* Die Routine zum Zeichnen des Häkchens habe ich im Programm um
* einige Zeilen nach Hinten verschoben. Jetzt wird erst der
* selectFill-Eintrag und dann das Häckchen gezeichnet. Das hat
* den Vorteil, daß auch ein falsch plaziertes Häkchen noch sichtbar
* bleibt. Vorher wurde es überschrieben und war deshalb nicht
* mehr zu sehen. J.
highComp,highBox,highItem,highNone: Genau wie unter Intuition bestimmen
diese Flags die Art der Hervorhebung. Falls kein Alternativ-Item
bei selectFill angegeben wurde, hat das den gleichen Effekt, als
wenn highNone gesetzt worden wäre.
* Falls ein Alternativ-Item bei selectFill angegeben war, dann
* wurden die Flags highComp und highBox in Derek Zahns Version
* von pop.c ignoriert. Das hatte den unschönen Effekt, daß
* alternative Texte nicht optisch hervorgehoben werden konnten.
* Dies habe ich geändert, sodaß jetzt highComp und highBox
* auch funktionieren wenn selectFill#NIL ist. J.
itemText: Funktioniert identisch zu Intuition.
itemEnabled: Ist dieses Flag nicht gesetzt, dann wird der Item
'unscharf' gezeichnet und kann nicht selektiert werden.
PopChoose() gibt -1 zurück, wenn versucht wird diesen
Item zu selektieren.
isDrawn,commSeq: Werden nicht verwendet.
Zum Anhang,Probleme vermerkt Derek Zahn:
Das Modul ist bei weitem noch nicht perfekt, wenn ich auch zugebe,
daß ich leider nicht in der Lage war, entweder bessere Lösungen
der Probleme anzubieten die mich etwas nervös machen; oder für eine
einfachere Implementation der noch fehlenden Funktionen zu sorgen.
Dieser Anhang soll etwas zur Verdeutlichung der Bedenken beitragen,
mit denen ich diesen Beitrag der Gemeinschaft der Amiga-Freunde zur
weiteren Verwendung überlasse.
Erstens ist da die Inkonsistenz der Benutzerschnittstelle: Obgleich ich
immer noch der Meinung bin, daß die Konsistenz die Benutzung des Intuition-
Message-Systems verlangt, scheint das vorliegende Konzept doch in fast
allen vorstellbaren Ungebungen zu funktionieren. Tatsächlich erscheint
es einfacher PopChoose() so zu verwenden, wie es jetzt ist. Verbesserungs-
vorschläge oder Erweiterungen der bestehenden Schnittstelle würde ich
jederzeit begrüßen.
Zweitens, die popRemember-Geschichte macht mich etwas nervös; die Werte von
leftEdge und TopEdge damit zu ändern, das sieht wie ein Trick aus.
Drittens, die Art in der der optionale Menütitel behandelt wird, sieht
etwas merkwürdig aus. Wenn man die Offsets der MenuItems vergrößert, dann
sollte man die Größe des Windows auch entsprechend anpassen. Aber ich
konnte mich nicht dazu durchringen, die Windowhöhe auch noch anzupassen.
Viertens, könnte der Source-Code vermutlich noch verbessert werden. Zu oft
wird die Liste der MenuItems durch gegangen, da könnte immer noch ein
Fehler auftauchen?
Fünftens, fehlen noch einige wesentliche Funktionen: SubItems und
nextSelect. Die Tataturbefehle fehlen vollständig; mir ist aber völlig
unklar, wie das gehen könnte.
Sechstens, Fehler: Es gibt zwei, von denen Derek weiß:
1. Obwohl der Fall des fehlenden popTidy-Flags unterstützt wird; das
PopUp-Menü erscheint nicht, wenn die Screen-Grenzen verletzt werden;
bin ich mir nicht so sicher, was unter Kickstart 1.1 dann passiert.
.... Sorry Derek, I coudn't exactly follow your remarks here...
2. Es kann passieren, daß der Anwender den Menü-Request durch Mausklick
beendet, bevor das Menü gezeichnet wurde. In diesem Fall wird die Menü-
auswahl nicht bemerkt und muß wiederholt werden. Dies könnte ich
abfangen, wenn ich herausfinden könnte, wie man den Zustand der Maus-
tasten sofort nach dem Öffnen des Windows abfragt.
Nachbemerkung des Übersetzers:
==============================
In pop.c verlangt Derek ausdrücklich, das ein explizite Zeiger auf
IntuitionBase und GraphicsBase existieren. Das macht zumindest für den
M2Amiga-Compiler keinen Sinn, der öffnet und schließt seine Libraries
selbständig. Auch die ürsprünglich zulässige Angabe winPtr:=NIL, mit der
Maßgabe, daß sich dann das PopUp-Menü an das (zufällig) gerade aktive
Fenster anhängt, ergibt für mich keinen Sinn. Ich habe es probiert, die
Ergebisse waren fast immer katastrophal. Deshalb habe ich dafür gesorgt,
daß PopChoose() sofort mit -1 zurückkehrt, falls menPtr oder winPtr gleich
NIL sind.
Die Files pop.def und pop.mod wurden mit dem M2Amiga-Compiler Version 3.2
kompiliert, deshalb können pop.sym und pop.obj nicht zusammen mit der
Demo-Version des M2Amiga verwendet werden (die Version 3.2 erzeugt einen
anderen Schlüssel im .sym-File). Damit Benutzer der Demo-Version des
M2Amiga aber trotzdem dieses PopUp-Menü verwenden können, habe ich pop.def
und pop.mod (in einer leicht geänderten Version) unter 3.11 kompiliert
und die entsprechenden Files pop.sym und pop.obj im Ordner 'Demo-Version'
abgelegt.
Viel Spaß mit dieser zusätzlichen Window-Option!
Jochen SIGMA für A.I.T. (16-2-89)